package cqie.personal.frame.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import cqie.personal.frame.bo.AddModifyMenuBO;
import cqie.personal.frame.bo.GetCharacterBO;
import cqie.personal.frame.bo.GetMenuBO;
import cqie.personal.frame.entity.MenuInfo;
import cqie.personal.frame.exception.ValidationFailException;
import cqie.personal.frame.mapper.CharacterInfoMapper;
import cqie.personal.frame.mapper.MenuInfoMapper;
import cqie.personal.frame.mapper.MenuViewMapper;
import cqie.personal.frame.service.MenuInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cqie.personal.frame.vo.MenuView;
import cqie.personal.frame.vo.PageVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Yeeeeee
 * @since 2021-09-03
 */
@Service
public class MenuInfoServiceImpl extends ServiceImpl<MenuInfoMapper, MenuInfo> implements MenuInfoService {

    @Resource
    MenuInfoMapper menuInfoMapper;
    @Resource
    MenuViewMapper menuViewMapper;
    @Resource
    UploadDownloadServiceImpl uploadDownloadService;
    @Resource
    CharacterInfoMapper characterInfoMapper;


    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_UNCOMMITTED)
    public synchronized boolean addMenu(AddModifyMenuBO menuBO) throws ValidationFailException {
        if(menuBO == null){
            throw new ValidationFailException("服务器抽风啦，刷新重试吧");
        }
        if(menuBO.getUid()==null){
            throw new ValidationFailException("权限错误");
        }
        if(menuBO.getMenuName() == null) {
            throw new ValidationFailException("菜单名字不能为空哦");
        }
        if(menuBO.getMenuFather()!=null){
            if(menuBO.getMenuAddress() == null){
                throw new ValidationFailException("未指定地址");
            }
        }
        QueryWrapper<MenuInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("menu_name",menuBO.getMenuName());
        if(menuInfoMapper.selectCount(wrapper)>0){
            throw new ValidationFailException("名字已经被占用了哦，换一个吧");
        }
        MenuInfo menu = new MenuInfo();
        Date date = new Date();
        menu.setCreatePerson(menuBO.getUid());
        menu.setCreateTime(date);
        menu.setLastUpgradePerson(menuBO.getUid());
        menu.setLastUpgradeTime(date);
        menu.setMenuName(menuBO.getMenuName());
        if(menuBO.getMenuFather()!=null){
            QueryWrapper<MenuInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id",menuBO.getMenuFather());
            MenuInfo father = menuInfoMapper.selectOne(queryWrapper);
            if(father == null){
                throw new ValidationFailException("啊拉，父亲节点不可用哦，是不是输错了呢");
            }
            menu.setMenuLevel(father.getMenuLevel()+1);
            menu.setMenuFather(menuBO.getMenuFather());
            menu.setMenuFatherName(father.getMenuName());
        }
        menu.setMenuAddress(menuBO.getMenuAddress());
        if(menuBO.getMenuAddress()!=null){
            menu.setMenuAddress(menuBO.getMenuAddress());
        }
        return menuInfoMapper.insert(menu)==1;
    }

    @Override
    public PageVO<List<MenuInfo>> getMenu(GetMenuBO getMenuBO) throws ValidationFailException {
        if(getMenuBO==null){
            throw new ValidationFailException("∑(っ°Д°;)っ服务器被玩坏了，但肯定不是服务器的错");
        }
        QueryWrapper<MenuInfo> queryWrapper = new QueryWrapper<>();
        if(getMenuBO.getId()!=null){
            queryWrapper.eq("id",getMenuBO.getId());
        }
        if(getMenuBO.getMenuName()!=null){
            queryWrapper.like("menu_name",getMenuBO.getMenuName());
        }
        if(getMenuBO.getMenuFather()!=null){
            queryWrapper.eq("menu_father_name",getMenuBO.getMenuFather());
        }
        if(getMenuBO.getMenuAddress()!=null){
            queryWrapper.likeRight("menu_address",getMenuBO.getMenuAddress());
        }
        if(getMenuBO.getMenuAbandon()!=null) {
            queryWrapper.eq("menu_abandon", getMenuBO.getMenuAbandon());
        }
        queryWrapper.last(" LIMIT "+getMenuBO.getPageOff()+" , " + getMenuBO.getPageMax());
        List<MenuInfo> menuInfoList = menuInfoMapper.selectList(queryWrapper);
        PageVO<List<MenuInfo>> result = new PageVO<>(menuInfoList);
        result.setPageNo(getMenuBO.getPageNo());
        result.setPageSize(getMenuBO.getPageMax());
        result.setRecordCount(menuInfoList.size());
        Integer totalCount = menuInfoMapper.selectCount(queryWrapper);
        if(totalCount == null){
            result.setTotalCount(0);
            result.setTotalPage(0);
        }else {
            result.setTotalCount(totalCount);
            result.setTotalPage(result.getTotalCount() % result.getPageSize() == 0 ?
                    result.getTotalCount() / result.getPageSize() :
                    result.getTotalCount() / result.getPageSize() + 1);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_UNCOMMITTED)
    public synchronized boolean modifyMenu(AddModifyMenuBO addModifyMenuBO , MultipartFile file) throws ValidationFailException {
        if(addModifyMenuBO == null){
            throw new ValidationFailException("∑(っ°Д°;)っ服务器被玩坏了，但肯定不是服务器的错");
        }
        if(addModifyMenuBO.getId() == null){
            throw new ValidationFailException("不指定修改的对象是不行的啦");
        }
        if(addModifyMenuBO.getMenuName() == null) {
            throw new ValidationFailException("菜单名字不能为空哦");
        }
        if(addModifyMenuBO.getMenuFather()!=null){
            if(addModifyMenuBO.getMenuAddress() == null){
                throw new ValidationFailException("未指定地址");
            }
        }
        MenuInfo menuInfo_old = menuInfoMapper.selectById(addModifyMenuBO.getId());
        MenuInfo menuInfo_new = new MenuInfo();
        if (!addModifyMenuBO.getMenuName().equals(menuInfo_old.getMenuName())) {
            QueryWrapper<MenuInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("menu_name", addModifyMenuBO.getMenuName());
            if (menuInfoMapper.selectCount(wrapper) > 0) {
                throw new ValidationFailException("名字已经被占用了哦，换一个吧");
            }
        }
        menuInfo_new.setMenuName(addModifyMenuBO.getMenuName());

        if(addModifyMenuBO.getMenuFather()!=null){
            QueryWrapper<MenuInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id",addModifyMenuBO.getMenuFather());
            MenuInfo father = menuInfoMapper.selectOne(queryWrapper);
            if(father == null){
                throw new ValidationFailException("啊拉，父亲节点不可用哦，是不是输错了呢");
            }
            menuInfo_new.setMenuLevel(father.getMenuLevel()+1);
            menuInfo_new.setMenuFather(addModifyMenuBO.getMenuFather());
            menuInfo_new.setMenuFatherName(father.getMenuName());
        }else {
            menuInfo_new.setMenuFather(null);
            menuInfo_new.setMenuLevel(0);
            menuInfo_new.setMenuFatherName(null);
        }
        menuInfo_new.setMenuAddress(addModifyMenuBO.getMenuAddress());
        menuInfo_new.setMenuAbandon(addModifyMenuBO.getMenuAbandon());
        if(file != null) {
            menuInfo_new.setMenuImg(uploadDownloadService.upload(file));
        }
        menuInfo_new.setLastUpgradeTime(new Date());
        menuInfo_new.setLastUpgradePerson(addModifyMenuBO.getUid());

        UpdateWrapper<MenuInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id",addModifyMenuBO.getId());
        return menuInfoMapper.update(menuInfo_new,updateWrapper)>0;
    }

    @Override
    public List<List<MenuView>>  getTreeMenu() {
        QueryWrapper<MenuView> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("menu_level",0)
                    .select(MenuView.class,item -> !item .getColumn().equals("child_list"));
        List<MenuView>  dataList = menuViewMapper.selectList(queryWrapper);
        QueryWrapper<MenuView> wrapper =new QueryWrapper<>();
        wrapper.ne("menu_level",0)
                .select(MenuView.class,item -> !item .getColumn().equals("child_list"));
        List<MenuView> sonList = menuViewMapper.selectList(wrapper);
        List<List<MenuView>> result = new ArrayList<>();
        for(MenuView menuView : dataList){
            List<MenuView> resultList = new ArrayList<>();
            getTree(menuView,resultList,sonList);
            result.add(resultList);
        }
        return result;
    }

    public List<MenuView>  getTreeMenu2() {
        QueryWrapper<MenuView> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("menu_level",0)
                .select(MenuView.class,item -> !item .getColumn().equals("child_list"));
        List<MenuView>  dataList = menuViewMapper.selectList(queryWrapper);
        QueryWrapper<MenuView> wrapper =new QueryWrapper<>();
        wrapper.ne("menu_level",0)
                .select(MenuView.class,item -> !item .getColumn().equals("child_list"));
        List<MenuView> sonList = menuViewMapper.selectList(wrapper);
        List<MenuView> result = new ArrayList<>();
        for(MenuView menuView :dataList){
            menuView.setChild(menuView,sonList);
            result.add(menuView);
        }
        return result;
    }

    @Override
    public List<MenuView> getUserMenu(Integer uid) {
        GetCharacterBO characterBO = new GetCharacterBO();
        characterBO.setUid(uid);
        String character =characterInfoMapper.getCharacterByUid(uid);
        String[] menuID = character.split(",");
        QueryWrapper<MenuView> menuViewQueryWrapper = new QueryWrapper<>();
        menuViewQueryWrapper.eq("menu_level",0)
                            .in("id", Arrays.asList(menuID))
                            .select(MenuView.class,item -> !item .getColumn().equals("child_list"));
        List<MenuView>  dataList = menuViewMapper.selectList(menuViewQueryWrapper);
        QueryWrapper<MenuView> wrapper =new QueryWrapper<>();
        wrapper.ne("menu_level",0)
                .in("id", Arrays.asList(menuID))
                .select(MenuView.class,item -> !item .getColumn().equals("child_list"));
        List<MenuView> sonList = menuViewMapper.selectList(wrapper);
        List<MenuView> result = new ArrayList<>();
        for(MenuView menuView :dataList){
            menuView.setChild(menuView,sonList);
            result.add(menuView);
        }
        return result;
    }

    private void getTree(MenuView menuView ,List<MenuView> tree ,List<MenuView> all){
        tree.add(menuView);
        List<MenuView> child = all.stream()
               .filter(x->x.getMenuFather()!=null&&x.getMenuFather().equals(menuView.getId()))
               .collect(Collectors.toList());
            for (MenuView menu : child) {
                getTree(menu, tree, all);
            }
    }

}
